#include "PrimaryGeometry.h"

#pragma region simpledrawing

void createCircleTable(double **sint,double **cost,const int n)
{
	int i;

	/* Table size, the sign of n flips the circle direction */

	const int size = abs(n);

	/* Determine the angle between samples */

	const double angle = 2*M_PI/(double)( ( n == 0 ) ? 1 : n );

	/* Allocate memory for n samples, plus duplicate of first entry at the end */

	*sint = (double *) calloc(sizeof(double), size+1);
	*cost = (double *) calloc(sizeof(double), size+1);

	/* Bail out if memory allocation fails, fgError never returns */

	if (!(*sint) || !(*cost))
	{
		free(*sint);
		free(*cost);
	}

	/* Compute cos and sin around the circle */

	(*sint)[0] = 0.0;
	(*cost)[0] = 1.0;

	for (i=1; i<size; i++)
	{
		(*sint)[i] = sin(angle*i);
		(*cost)[i] = cos(angle*i);
	}

	/* Last sample is duplicate of the first */

	(*sint)[size] = (*sint)[0];
	(*cost)[size] = (*cost)[0];
}
#pragma endregion simpledrawing

#pragma region testBug
void drawFrustum(float width,float height,float frush_Near,float frush_Far)
{
	frush_Near*=(-1);
	frush_Far*=(-1);
	glColor3f(1,0,0);
	glBegin(GL_LINE_LOOP);
	glVertex3f(-width/2,-height/2,frush_Far);
	glVertex3f(-width/2,height/2,frush_Far);
	glVertex3f(width/2,height/2,frush_Far);
	glVertex3f(width/2,-height/2,frush_Far);
	glEnd();

	glBegin(GL_LINE_LOOP);
	glVertex3f(-width/2,-height/2,frush_Near);
	glVertex3f(-width/2,height/2,frush_Near);
	glVertex3f(width/2,height/2,frush_Near);
	glVertex3f(width/2,-height/2,frush_Near);
	glEnd();

	glBegin(GL_LINES);
	glVertex3f(-width/2,-height/2,frush_Far);
	glVertex3f(-width/2,-height/2,frush_Near);

	glVertex3f(-width/2,height/2,frush_Far);
	glVertex3f(-width/2,height/2,frush_Near);

	glVertex3f(width/2,height/2,frush_Far);
	glVertex3f(width/2,height/2,frush_Near);

	glVertex3f(width/2,-height/2,frush_Far);
	glVertex3f(width/2,-height/2,frush_Near);

	glEnd();
}


#pragma endregion testBug

void pushToVer(float * v,float p[3],int &offset)
{
	memcpy(v+offset,p,sizeof(float)*3);
	offset+=3;
}

void createSphereVertices(GLfloat * vertices,float radius,GLint slices,GLint stacks)
{
	int num_vertices = (slices+2)*2 + (stacks-2)*(slices+1)*2;
	int vIndex = 0;

	double *sint1,*cost1;
	double *sint2,*cost2;

	createCircleTable(&sint1,&cost1,-slices);
	createCircleTable(&sint2,&cost2,stacks*2);

	/* Adjust z and radius as stacks are drawn. */
	double z0,z1;
	double r0,r1;

	/* The top stack is covered with a triangle fan */
	z0 = 1.0;
	z1 = cost2[(stacks>0)?1:0];
	r0 = 0.0;
	r1 = sint2[(stacks>0)?1:0];

	float pTop[3] = {0,0,radius};
	pushToVer(vertices,pTop,vIndex);

	for (int j=slices; j>=0; j--)
	{
		float tmp[3]={float(cost1[j]*r1*radius), float(sint1[j]*r1*radius), float(z1*radius)};
		pushToVer(vertices,tmp,vIndex);
	}

	for(int i=1; i<stacks-1; i++ )
	{
		z0 = z1; z1 = cost2[i+1];
		r0 = r1; r1 = sint2[i+1];
		for(int j=0; j<=slices; j++)
		{
			float tmp1[3] = {float(cost1[j]*r1*radius),float(sint1[j]*r1*radius),float(z1*radius)};
			float tmp2[3] = {float(cost1[j]*r0*radius),float(sint1[j]*r0*radius),float(z0*radius)};
			pushToVer(vertices,tmp1,vIndex);
			pushToVer(vertices,tmp2,vIndex);
		}
	}

	z0 = z1;
	r0 = r1;
	float pBot[3] = {0,0,-radius};
	pushToVer(vertices,pBot,vIndex);

	for (int j=0; j<=slices; j++)
	{
		float tmp[3] = {float(cost1[j]*r0*radius),float(sint1[j]*r0*radius),float(z0*radius)};
		pushToVer(vertices,tmp,vIndex);
	}
}

void createCyliderVertices(GLfloat * vertices,GLfloat radius,int slices)
{
	int num_vertices = (slices+2)*2 + (slices+1)*2;
	int vIndex = 0;
	float height = 1;
	int j;

	/* Pre-computed circle */

	double *sint,*cost;

	createCircleTable(&sint,&cost,-slices);

	/* Cover the base and top */
	float pTop[3] = {0,height,0};
	pushToVer(vertices,pTop,vIndex);

	for (j=0; j<=slices; j++)
	{
		float tmp[3]={(float)cost[j]*radius, height, (float)sint[j]*radius};
		pushToVer(vertices,tmp,vIndex);
	}

	float pBot[3] = {0,0,0};
	pushToVer(vertices,pBot,vIndex);
	for (j=slices; j>=0; j--)
	{
		float tmp[3]={(float)cost[j]*radius, 0, (float)sint[j]*radius};
		pushToVer(vertices,tmp,vIndex);
	}

	/* Do the stacks */
	for (j=0; j<=slices; j++ )
	{
		float tmp1[3]={(float)cost[j]*radius, 0, (float)sint[j]*radius};
		float tmp2[3]={(float)cost[j]*radius, height, (float)sint[j]*radius};
		pushToVer(vertices,tmp1,vIndex);
		pushToVer(vertices,tmp2,vIndex);
	}


	/* Release sin and cos tables */

	free(sint);
	free(cost);
}

void createConeVertices(GLfloat * vertices,GLfloat botRadius,GLfloat topRadius,GLfloat height,GLint slices)
{
	double *sint,*cost;
	int vIndex = 0;
	createCircleTable(&sint,&cost,-slices);

	for(int j=0; j<=slices; j++){
		float tmp1[3]=	{(float)cost[j]*botRadius,0,(float)sint[j]*botRadius};
		float tmp2[3]=	{(float)cost[j]*topRadius,height,(float)sint[j]*topRadius};
		pushToVer(vertices,tmp1,vIndex);
		pushToVer(vertices,tmp2,vIndex);
	}
}

//HARD CODE :))
void createDisplayList(GLuint& buff,GLuint& dipslayList)
{
	dipslayList = glGenLists(1);
	glNewList(dipslayList, GL_COMPILE);

	glBindBufferARB(GL_ARRAY_BUFFER_ARB, buff);
	glColor3f(0,0,1);
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT, 0, 0);
	glDrawArrays(GL_QUAD_STRIP,0,50);
	glDisableClientState(GL_VERTEX_ARRAY);
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

	glEndList();
}